home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
ddj1190.arc
/
TOOKE.ASC
< prev
next >
Wrap
Text File
|
1990-10-27
|
10KB
|
376 lines
_OBJECT-ORIENTED DEBUGGING_
by Simon Tooke
[LISTING ONE]
#ifndef STRING_H
#define STRING_H
#include <string.h>
#include <memory.h>
#include <malloc.h>
#ifdef NULL
# undef NULL
#endif
#define NULL 0
typedef enum { False, True } Boolean;
// a String is a simple implementation of a C++ string class
class String
{
char *s; // actual pointer to text
public:
String(void) { s = strdup(""); }
String(char *c) { s = strdup(c); }
String(char *c, int n) { s = new char[n+1]; memcpy(s,c,n); s[n]=0; }
String(String &ss, char *c) { s = malloc(strlen(ss.s)+strlen(c)+1);
strcpy(s,ss.s); strcat(s,c); }
String(String &ss) { s = strdup(ss.s); }
~String(void) { delete s; }
operator char *(void) { return s; }
String& operator +(char *c) { String *a = new String(*this,c); return *a;}
String& operator +=(char *c) { *this = *this + c; return *this; }
String& operator =(char *c) { delete s; s = strdup(c); return *this; }
String& operator =(String& a){ delete s; s = strdup(a.s); return *this; }
operator ==(char *c) const;
operator ==(String *c) const;
#ifdef DEBUG
void dump() const;
Boolean verify() const;
#endif /*DEBUG*/
};
// a StringListElement is a single item in a StringList
class StringListElement
{
String s; // this String in the list
StringListElement *next; // pointer to next element in list
public:
StringListElement(void) : next(NULL), s("") {}
StringListElement(char *c) : next(NULL), s(c) {}
StringListElement(char *c, int n) : next(NULL), s(c,n) {}
StringListElement(String &ss) : next(NULL), s(ss) {}
~StringListElement(void) { if (next) delete next; next=NULL; }
friend class StringList;
friend class StringListIterator;
#ifdef DEBUG
void dump() const;
Boolean verify() const;
#endif /*DEBUG*/
};
// a StringList is a simple single-linked list of strings
class StringList
{
StringListElement *head; // first String in list
StringListElement *tail; // last String in list
public:
StringList(void) : head(NULL), tail(NULL) {}
StringList(String& ss) { head = tail = new StringListElement(ss); }
StringList(char *ss) { head = tail = new StringListElement(ss); }
~StringList(void) { if (head) { delete head; head=NULL; } }
String& find(char *s) const;
void clear(void) { delete head; head = tail = NULL; }
StringList& operator +=(StringList& xx);
StringList& operator +=(char *ss);
StringList& operator +=(String& ss);
StringList& operator =(StringList& xx);
operator int();
friend class StringListIterator;
#ifdef DEBUG
void dump() const;
Boolean verify() const;
#endif /*DEBUG*/
};
// a StringListIterator is a method of traversing a list of strings
class StringListIterator
{
const StringList *list; // StringList to be traversed
StringListElement *nxt; // current String in StringList
public:
StringListIterator(void) : list(NULL), nxt(NULL) {}
StringListIterator(const StringList *l) : list(l), nxt(l->head) {}
String *next(void);
void reset() { nxt = (list != NULL) ? list->head: NULL; }
int anymore() const { return (nxt != NULL); }
StringListIterator& operator =(const StringList& ss);
#ifdef DEBUG
void dump() const;
Boolean verify() const;
#endif /*DEBUG*/
};
#endif // STRING_H
[LISTING TWO]
#include <stream.h>
#include "String.h"
int main (int, char *[])
{
String a("Hello ");
String *b = new String("world.");
String c;
c = a + *b + "\n";
cout << "a + b = " << (char *)c;
cout << "a = " << (char *)a << "\n";
cout << "b = " << (char *)*b << "\n";
StringList l(a);
l += *b;
l.dump();
}
[LISTING THREE]
#ifndef ASSERT_HDR
#define ASSERT_HDR
#ifdef DEBUG
extern void _assertRtn(char *, int);
# define assert(condition) \
if (condition) ; else _assertRtn(__FILE__,__LINE__);
#else /*ifndef DEBUG*/
# define assert(condition)
#endif
#endif /*ASSERT_HDR*/
[LISTING FOUR]
#include <stream.h>
#ifdef DEBUG
void _assertRtn(char *file, int line)
{
cerr << "\nAssertion Failure in file '" << file
<< "' line " << line << "\n";
line = 0; line /= line; // force core dump
}
#endif
[LISTING FIVE]
#include "String.h"
#include "Assert.h"
#ifdef DEBUG
# include <stream.h>
#endif
/***** String class ******/
// String comparison operator
String::operator ==(char *c) const
{
assert(this->verify());
// compare String to char array
return strcmp(s,c) == 0;
}
// String comparison operator
String::operator ==(String *c) const
{
assert(this->verify());
// compare String to String
return strcmp(s,(char *)c) == 0;
}
#ifdef DEBUG
void String::dump(void) const
{
assert(this->verify());
cerr << "String(\"" << s << "\")";
}
Boolean String::verify(void) const
{
// Strings must always point to something.
if (s == NULL) return False;
return True;
}
#endif
/****** StringList class (and StringListElement) ******/
StringList& StringList::operator +=(String& ss)
{
assert(this->verify());
if (tail)
{
tail->next = new StringListElement(ss);
tail = tail->next;
}
else
head = tail = new StringListElement(ss);
return *this;
}
StringList& StringList::operator +=(char *ss)
{
assert(this->verify());
if (tail)
{
tail->next = new StringListElement(ss);
tail = tail->next;
}
else
head = tail = new StringListElement(ss);
return *this;
}
StringList& StringList::operator +=(StringList& xx)
{
assert(this->verify());
// add new list to old list item by item
for (StringListElement *le=xx.head; le; le=le->next)
*this += le->s;
return *this;
}
// StringList assignment operator (performs deep copy)
StringList& StringList::operator =(StringList& xx)
{
assert(this->verify());
// get rid of old list
clear();
// add new list to (clear) old list item by item
for (StringListElement *le=xx.head; le; le=le->next)
*this += le->s;
// return new copy of old list
return *this;
}
// (int)(StringList) cast returns number of strings in list
StringList::operator int()
{
int count = 0;
StringListIterator ll(this);
assert(this->verify());
while (ll.next() != NULL)
count++;
return count;
}
#ifdef DEBUG
//
// dump() - display instance in format "StringList(...)"
//
void StringList::dump(void) const
{
// check consistancy
assert(this->verify());
// print header
cerr << "StringList(";
// use StringListElement::dump() to recursively display all members
if (head != NULL) head->dump();
// print trailer
cerr << ")\n";
}
Boolean StringList::verify(void) const
{
// if there are elements in this list, ensure they are valid.
// (note that head->verify() ensures the entire list is valid.)
if ((head!=NULL) && !head->verify()) return False;
// Both the head and tail must either be null or non-null.
if ((head!=NULL) && (tail==NULL)) return False;
if ((head==NULL) && (tail!=NULL)) return False;
return True;
}
#endif /*DEBUG*/
#ifdef DEBUG
void StringListElement::dump(void) const
{
assert(this->verify());
s.dump();
if (next != NULL)
{
cerr << ',';
next->dump();
}
}
Boolean StringListElement::verify(void) const
{
// An element of a list of Strings must point to a valid String.
if ((char *)(s) == NULL) return False;
if (!s.verify()) return False;
// If there is another element within this list, it must be valid.
if ((next!=NULL) && !next->verify()) return False;
return True;
}
#endif
/****** StringListIterator class ******/
// assignment operator
StringListIterator& StringListIterator::operator =(const StringList& ss)
{
assert(this->verify());
list = &ss;
nxt = ss.head;
return *this;
}
// get next item in list of strings pointed to by iterator
String *StringListIterator::next(void)
{
assert(this->verify());
if (list == NULL) return NULL; // no StringList, so no next item
if (nxt == NULL) return NULL; // at end of list, so no next item
String *aa = &(nxt->s); // save pointer to String
nxt = nxt->next; // point to next item in list
return aa; // return pointer to String
}
#ifdef DEBUG
Boolean StringListIterator::verify(void) const
{
// if there is a list available, verify it.
if (!list->verify()) return False;
// if we haven't reached the end of the list,
// verify the next element
if (nxt != NULL && !nxt->verify()) return False;
// everything appears correct
return True;
}
#endif /*DEBUG*/
[LISTING SIX]
CC = CC
CFLAGS = -DDEBUG
prog : main.o String.o lib.o
$(CC) main.o String.o lib.o -o prog
String.o : String.C String.h
$(CC) -c $(CFLAGS) String.C
main.o : main.C String.h
$(CC) -c $(CFLAGS) main.C
lib.o : lib.C
$(CC) -c $(CFLAGS) lib.C
clean :
rm -f *.o a.out core
clobber : clean
rm -f prog